import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.*;

import java.net.*;

import javax.imageio.ImageIO;
import javax.swing.*;
public class EmailServer
{
	public static EmailCommands savedEmails[] = new EmailCommands[500]; // array that stores email objects
	public static int numberOfEmails, deleteID; // how many emails are in the array and what id to delete
	
	
	public static void main(String[] args)
							throws IOException // server connection information and client handling 
	{
		
		ServerSocket serverSocket = null;
		final int PORT = 12349;
		Socket client;
		ClientHandler handler;
		

		try
		{
			serverSocket = new ServerSocket(PORT);
		}
		catch (IOException ioEx)
		{
			System.out.println("\nUnable to set up port!");
			System.exit(1);
		}

		System.out.println("\nServer running...\n");
		
		do
		{
			client = serverSocket.accept();
			//Wait for client.
			System.out.println("\nNew client accepted.\n");
			handler = new ClientHandler(client);
			handler.start();
		}while (true);
		
	}
	public static void saveMessage( EmailCommands emailToSave)  // takes in the email object passed in from the client and saved it to an array of the said object
	{
		emailToSave.setFileLocation("NON");
		savedEmails[numberOfEmails] = emailToSave;
		numberOfEmails++;
		System.out.println("FROM : " + emailToSave.getUsername() + " TO : " + emailToSave.getRecipient() + " Messaage '" + emailToSave.getMessage() + "' was stored");
	}
	public static void saveMessageWithAttachment( EmailCommands emailToSave, String fileLocation)  // takes in the email object passed in from the client and saved it to an array of the said object
	{
		emailToSave.setFileLocation(fileLocation);
		savedEmails[numberOfEmails] = emailToSave;
		numberOfEmails++;
		System.out.println("FROM : " + emailToSave.getUsername() + " TO : " + emailToSave.getRecipient() + " Messaage '" + emailToSave.getMessage() + "' was stored " + "With file " + fileLocation);
	}
	
	public static EmailCommands collectMessages(int i) //returns all the email objects to the calling function to allow for sorting to the correct user 
	{	
		return savedEmails[i]; 		
	}
	
	public static int getNumberOfEmails() //  returns the number of emails in the email object array to the calling function
	{
		return numberOfEmails;
	}
	
	public static void deleteEmail( String emailToDelete) // this function takes in the object to delete and compares it to all the emails in the array, if there's a exact match it nulls the object in the arr and re orders it  
	{
		int deletedIndex = numberOfEmails;
		for (int i = 0; i < numberOfEmails; ++i)
		{
			if(savedEmails[i].getMessage().equals(emailToDelete))
			{
				savedEmails[i] = null;
				deletedIndex = i;
			}
		}
		for (int i = deletedIndex; i < numberOfEmails; ++i)
		{
			savedEmails[i] = savedEmails[i + 1];
		}
		numberOfEmails--;
	}
	
}

class ClientHandler extends Thread // exicuted when a client is connected, creates a thread for each client
{
	private Socket client;
	private ObjectInputStream inputStream; 
	private ObjectOutputStream outputStream;
	
	public ClientHandler(Socket socket) throws IOException// exicuted when a client is connected, sets the read and output steams and allows the client to issues commands
	{
	{
		client = socket;
		inputStream = new ObjectInputStream(client.getInputStream());
		outputStream = new ObjectOutputStream(client.getOutputStream());		
	}
	}

	public void run()
	{
		do
			{
				EmailCommands clientsCommand;
				try 
				{
					clientsCommand = (EmailCommands) inputStream.readObject();
					String clientCommand = clientsCommand.clientCommand();
					//String userCommand = clientsCommand.getUsername();
					
					if(clientCommand.equals("send"))
					{
						System.out.println("FROM : " + clientsCommand.getUsername() + " TO : " + clientsCommand.getRecipient());
						EmailServer.saveMessage(clientsCommand); // calls save message and passes in the message to save from the client
						//EmailServer.collectMessages(i);
					} 
					
					else if(clientCommand.equals("retreieve"))
					{
						//System.out.println(userName);
						System.out.println("GET EMAILS FOR : " + clientsCommand.getUsername());
						getAllEmails(clientsCommand.getUsername(), clientsCommand); //calls get message and passes in the username for the messages that are wanted
						//System.out.println(clientCommand);
						
					}
					else if(clientCommand.equals("delete"))
					{
						deleteEmail(clientsCommand); //calls get message and passes in the message that wants to be deleted
						System.out.println(clientCommand);
					}
					else if (clientCommand.equals("login"))
					{
						String userName = clientsCommand.getUsername();
						System.out.println(userName + " has logged in");
					}
					else if (clientCommand.equals("file"))
					{
						System.out.println("Recieveing file");
						saveFile(clientsCommand);
					}
				}
				catch (IOException e) 
					{
						System.out.println("ERROR: Command not recieved");
					} 
					catch (ClassNotFoundException e) 
					{
						System.out.println("ERROR: Please reinstall the server");
					}
				
				
			}
			while ("QUIT".equals("QUIT"));
			
			try
			{
				System.out.println("Closing down connection...");
				client.close();
			}
			catch(IOException ioEx)
			{
				System.out.println("* Disconnection problem! *");
			}

	} 
	
	public void getAllEmails(String user, EmailCommands command) throws IOException // pulls all the emails from the email array one and one and filters out the required emails by the username
	{
		System.out.println("GETTING EMAILS FOR " + user);
		int numEmails = EmailServer.getNumberOfEmails();
		for (int i = 0; i < numEmails; ++i)
		{
			EmailCommands getAllEmails = EmailServer.collectMessages(i);
			System.out.println(getAllEmails.fileBytes());
			System.out.println(getAllEmails.fileLocation());
			
			System.out.println("GET EMAILS FOR : " + user + " COMPARE AGAINST " + getAllEmails.getRecipient());
			if (!getAllEmails.fileLocation().equals("NON"))
			{
				if (user.equals(getAllEmails.getRecipient()))
				{
					File file = new File(getAllEmails.fileLocation());
					System.out.println("This file is being sent " + file.getName());
					getAllEmails.setFile(file);					
					System.out.println("GOT EMAIL FOR " + user);
					getAllEmails.setClientCommand("email+file");
					try 
					{
						outputStream.writeObject(getAllEmails);
						///System.out.println(getAllEmails.fileBytes().getName());
					} 
					catch (IOException e) 
					{
						
					}
				}
			}
			else 
			{
				if (user.equals(getAllEmails.getRecipient()))
				{
					System.out.println("GOT EMAIL FOR " + user);
					getAllEmails.setClientCommand("email");
					try 
					{
						outputStream.writeObject(getAllEmails);
					} 
					catch (IOException e) 
					{
						
					}
			}
			}
		}
	}
	
	public void deleteEmail(EmailCommands emailsToDelete) //passes over the required message that needs to be deleted from the array
	{
		
		int deleteID = emailsToDelete.arrayID();
		String messageToDelete = emailsToDelete.getMessage();
		EmailServer.deleteEmail(messageToDelete);
		System.out.println("it's gonna delete!");
		System.out.println(deleteID);
		System.out.println(messageToDelete);
	}
	public void saveFile(EmailCommands fileToSave) throws IOException
	{
		File file = fileToSave.fileBytes();
		String newFileLocation;
		boolean location = true;
		if (location)
		{
			newFileLocation = "C:/Users/Tom/Desktop/Email_Assignment1/attachments" + file.getName();
		}
		else 
		{
			newFileLocation = "F:\\MyWork\\javadev\\workspace\\Email_Assignment1\\attachments\\" + file.getName();
		}
		
		//String newFileLocation = "C:/Users/Tom/Desktop/Email_Assignment1/attachments" + file.getName();
		File newFile = new File(newFileLocation);
		FileInputStream fin = new FileInputStream(file);
		long fileLen =  (file.length());
		System.out.println("saving file of size " + fileLen);
		int intFileLen = (int)fileLen;
		byte[] byteArray = new byte[intFileLen];
		fin.read(byteArray);
		fin.close();
		FileOutputStream fos = new FileOutputStream(newFile);
		fos.write(byteArray);
		fos.flush();
		EmailServer.saveMessageWithAttachment(fileToSave, newFileLocation);
	}
}